<?php
class Permissions extends Dao
{
	private static $_instance = null;
	protected $_db = null, $_cache = null;
	
	protected function __construct()
	{
		parent::__construct();
	}
	
	public static function getInstance() 
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
	
	public function getListPermissions(array $args = array()){
		try{
			$defaults = array(		
			);
			$args = $this->args_merge($defaults, $args);
			
			$cmd = $this->_db->createCommand('SELECT SQL_CALC_FOUND_ROWS * FROM tbl_permissions ORDER BY module, permission_name');
			
			$arrResults = $cmd->queryAll();
			return $arrResults;
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function getRolePermissions($roleId, $module = null){
		if(empty($roleId)) throw new Exception('Role id can not null');
		try{
			//get role permissions
			$strSql = " SELECT p.permission_id, p.permission_name, rp.value
						FROM tbl_role_permission rp INNER JOIN tbl_permissions p ON ( rp.permission_id = p.permission_id AND module = IFNULL(:module, module) )
						WHERE rp.role_id=:rid
						ORDER BY p.module, p.permission_name";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":rid",$roleId,PDO::PARAM_STR);
			$cmd->bindParam(":module",$module,PDO::PARAM_STR);
			$arrRolePermissions = $cmd->queryAll();
			
			//get default system permissions
			$strSql = "SELECT * FROM tbl_permissions WHERE module = IFNULL(:module, module) ORDER BY module, permission_name";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":module",$module,PDO::PARAM_STR);
			$arrDefaultPermissions = $cmd->queryAll();
			
			//merge permissions
			$arrPermissions = array();
			$arrRp = array();
			foreach($arrRolePermissions as $R){
				$arrRp[$R['permission_id']] = $R;
			}
			$arrDp = array();
			foreach($arrDefaultPermissions as $R){
				$arrDp[$R['permission_id']] = $R;
			}
			$arrPermissions = array_values($arrRp+$arrDp);
			return $arrPermissions;
		} catch(Exception $ex){
			
		}
	}
	
	public function updateRolePermissions($roleId, array $arrPermissions){
		if(empty($roleId)) throw new Exception('Role id can not null');
		try{
			//remove old permissions
			$this->_db->createCommand()->delete('tbl_role_permission', 'role_id=:rid', array(':rid'=>$roleId));
			//update new permissions
			foreach($arrPermissions as $permissionId => $value){
				$args = array(
					'role_id' => $roleId,
					'permission_id' => $permissionId,
					'value' => $value
				);				
				$this->_db->createCommand()->insert('tbl_role_permission', $args);
			}
			return 1;
		} catch(Exception $ex){
			
		}
	}
	
	public function getUserPermissions($userId, $module = null){
		if(empty($userId)) throw new Exception('User id can not null');
		try{
			//get user permissions
			$strSql = "	SELECT up.*
						FROM (
								SELECT p.permission_id, p.permission_name, up.`value`
								FROM tbl_user_permission up INNER JOIN tbl_permissions p ON (up.permission_id = p.permission_id AND user_id = :uid AND module = IFNULL(:module, module))
								ORDER BY p.module, p.permission_name
							 ) up INNER JOIN (
								SELECT p.permission_id, p.permission_name, rp.`value`
								FROM (SELECT role_id FROM tbl_user_role WHERE user_id = :uid) ur INNER JOIN tbl_role_permission rp ON (ur.role_id = rp.role_id AND rp.value = 1)
								INNER JOIN tbl_permissions p ON (rp.permission_id = p.permission_id AND module = IFNULL(:module, module))
							 ) rp on rp.permission_id = up.permission_id
					  ";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":uid",$userId,PDO::PARAM_STR);
			$cmd->bindParam(":module",$module,PDO::PARAM_STR);
			$arrUserPermissions = $cmd->queryAll();
			//get allowed role permissions which user involved in
			$strSql = "	SELECT p.permission_id, p.permission_name, rp.`value`
						FROM (SELECT role_id FROM tbl_user_role WHERE user_id = :uid) ur INNER JOIN tbl_role_permission rp ON (ur.role_id = rp.role_id AND rp.value = 1)
							 INNER JOIN tbl_permissions p ON (rp.permission_id = p.permission_id AND module = IFNULL(:module, module))
						ORDER BY module, permission_name
					  ";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":uid",$userId,PDO::PARAM_STR);
			$cmd->bindParam(":module",$module,PDO::PARAM_STR);
			$arrRolePermissions = $cmd->queryAll();
			//merge permissions
			$arrPermissions = array();
			$arrUp = array();
			foreach($arrUserPermissions as $R){
				$arrUp[$R['permission_id']] = $R;
			}
			$arrRp = array();
			foreach($arrRolePermissions as $R){
				$arrRp[$R['permission_id']] = $R;
			}
			$arrPermissions = array_values($arrUp+$arrRp);
			return $arrPermissions;
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function updateUserPermissions($userId, array $arrPermissions){
		if(empty($userId)) throw new Exception('User id can not null');
		try{
			//remove old permissions
			$this->_db->createCommand()->delete('tbl_user_permission', 'user_id=:uid', array(':uid'=>$userId));
			//update new permissions
			foreach($arrPermissions as $permissionId => $value){
				$args = array(
					'user_id' => $userId,
					'permission_id' => $permissionId,
					'value' => $value
				);		
				$this->_db->createCommand()->insert('tbl_user_permission', $args);
			}			
			return 1;
		} catch(Exception $ex){
			
		}
	}
}